using System;
using System.Collections.Generic;
using System.Text;

namespace VerticalProcesses
{
    /// <summary>
    /// This is a static class providing a variety of methods for interpolating climate data
    /// within the model.
    /// </summary>
    static class Interpolation
    {
        /// <summary>
        /// A simple interpolation of variable using a linear lapse rate from a known observation
        /// (ValueOrig) at a given elevation (Zorig). Commonly used for temperature interpolation.
        /// </summary>
        /// <param name="Zorig">Elevation of observation</param>
        /// <param name="Z">Elevation sought</param>
        /// <param name="ValueOrig">Observation value</param>
        /// <param name="Rate">Linear rate of change with elevation</param>
        /// <returns></returns>
        static public double LinearChangeWithElevation(double Zobs, double ValueObs, double Z, double Rate)
        {
            return ValueObs + Rate * (Z - Zobs);
        }
    
        static public double FractionalChangeWithElevation(double Zobs, double ValueObs, double Z, double Rate)
        {
            return Math.Max(ValueObs * (1.0 + Rate * (Z - Zobs)),0);
        }

        static public double InverseDistanceWithLinearElevationCorrection(double[,] XYZobs, double[] ValueObs, double[] XYZ, double Zrate)
        {
            double sum = 0.0;
            double sumWeight = 0.0;
            for (int i = 0; i < ValueObs.Length; i++)
            {
                // correct observation based on lapse rate
                double elevCorrObs = LinearChangeWithElevation(XYZobs[i, 3], ValueObs[3], XYZ[3], Zrate);
                // inverse distance weighting
                double dist = Math.Sqrt( Math.Pow((XYZobs[i, 0] - XYZ[0]), 2) + Math.Pow((XYZobs[i, 1] - XYZ[1]), 2) );
                sumWeight += 1 / dist;
                sum += (1 / dist) * elevCorrObs;
            }

            return (sum / sumWeight);
        }

    }
}
